#include <stdio.h>

// 字符串常量是共享的
void test_01() {
    char *p1 = "Hello World!";
    char *p2 = "Hello World!";
    char *p3 = "Hello World!";

    printf("p1 = %p\n", p1);
    printf("p2 = %p\n", p2);
    printf("p3 = %p\n", p3);
    printf("Hello World = %p", "Hello World!");
}

// 字符串常量是不能修改的
void test_02() {
    char *p1 = "Hello World!";

    p1[0] = "A"; // SIGSEGV (Segmentation fault)
    printf("%s\n", p1);
}

int main() {
    // const 修饰的变量不能通过该变量修改其中的值
    const int number_value_01 = 100; //  数据存放在栈区, 伪常量
    // number_value_01 = 300; // 修改失败

    // const 修饰的变量可以通过指针更改变量的值(一般来说, 这样的操作是不允许的)
    printf("number_value_01 = %d\n", number_value_01);
    int *p_01 = &number_value_01;
    *p_01 = 300;
    printf("number_value_01 = %d\n", number_value_01);

    // 指针常量
    // 可以修改指针指向的地址, 但是不可以通过指针常量修改其指向地址的值
    int number_value_02 = 200;
    int number_value_03 = 300;

    const int *p_02 = &number_value_02;
    p_02 = &number_value_03; // 修改成功
    // *p_02 = 200; // 修改失败

    // 常量指针
    // 不可以修改指针指向的地址, 但是可以通过常量指针修改其指向地址的值
    int *const p_03 = &number_value_02;
    // p_03 = &number_value_03; //修改失败
    *p_03 = 300;

    // 既是指针常量又是常量指针
    // 不可以修改指针指向的地址, 但是不可以通过指针常量修改其指向地址的值
    const int *const p_04 = &number_value_02;
    // p_04 = &number_value_03; //修改失败
    // *p_04 = 400; // 修改失败

    test_01();

    // test_02();
}

// const 修饰的全局变量
// 1. 直接修改: 失败
// 2. 间接修改: 语法通过, 运行失败(受常量区保护)

// const 修饰的局部变量
// 1. 直接修改: 失败
// 2. 间接修改: 成功(一般来说, 这样的操作是不允许的)